﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Serialization;

namespace ProjectTW.Foliage
{
    /// <summary>
    /// Chunk基类，可以实现FoliageChunk或OtherChunk
    /// </summary>
    [ExecuteInEditMode]
    public class ChunkBase : MonoBehaviour
    {
        public int Id;
        public Vector2 MinPoint;
        public Vector2 MaxPoint;

        public int X;
        public int Z;
        
        [SerializeField]
        private Vector2 m_Position;
        [SerializeField]
        protected Vector3 m_Position3D;
        [SerializeField]
        protected Vector3 m_WorldPosition3D;

        [SerializeField]
        private Vector2 m_Size;
        [SerializeField]
        private Vector2 m_Extents;

        public Vector2 Position
        {
            get
            {
                return m_Position;
            }
            set
            {
                m_Position = value;

                MinPoint = Position;
                MaxPoint = Position + Size;

                m_Position3D = new Vector3(Position.x, 0, Position.y);
            }
        }

        public Vector3 Position3D
        {
            get
            {
                return m_Position3D;
            }
        }

        public Vector3 WorldPosition3D
        {
            get
            {
                return m_WorldPosition3D;
            }
        }

        public Vector2 Size
        {
            get
            {
                return m_Size;
            }
            set
            {
                m_Size = value;
                m_Extents = value / 2;

                OnSizeChanged();
            }
        }

        public Vector2 Extents
        {
            get
            {
                return m_Extents;
            }
            set
            {
                Extents = value;
                m_Size = value * 2;
            }
        }

        public Vector2 Center
        {
            get
            {
                return new Vector2(Position.x + (Size.x / 2), Position.y + (Size.y / 2));
            }
        }

        protected virtual string ChunkType
        {
            get
            {
                return "Default";
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sector"></param>
        /// <param name="position"></param>
        /// <param name="x"></param>
        /// <param name="z"></param>
        /// <param name="scale"></param>
        /// <param name="chunkId"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T CreateChunk<T>(SectorBase sector, Vector2 position, int x, int z, Vector2 scale, short chunkId) where T : ChunkBase
        {
            GameObject chunkObject = new GameObject();
            chunkObject.transform.parent = sector.transform;

            chunkObject.transform.localPosition = new Vector3(position.x, 0, position.y);
            chunkObject.transform.localRotation = Quaternion.identity;
            chunkObject.transform.localScale = Vector3.one;

            T chunk = chunkObject.AddComponent<T>();

            chunk.Position = position;
            chunk.m_Position3D = new Vector3(position.x, 0, position.y);
            chunk.m_WorldPosition3D = chunkObject.transform.position;
            chunk.Size = scale;

            chunk.X = x;
            chunk.Z = z;

            chunk.MinPoint = position;
            chunk.MaxPoint = position + scale;
            chunk.Id = chunkId;

            chunkObject.name = chunk.ChunkType + " Chunk : " + position;

            if (!Application.isPlaying)
            {
                chunk.Awake();
            }

            chunk.OnCreated();

            return chunk;
        }

        protected virtual void OnSizeChanged()
        {
        }

        public virtual void Awake()
        {
        }

        protected virtual void OnEnable()
        {
        }

        protected virtual void OnDisable()
        {
        }

        public bool Contains(Vector2 point, float offset)
        {
            return Contains(new Vector3(point.x, 0, point.y), offset);
        }

        public bool Contains(Vector3 point, float offset)
        {
            Vector2 size = new Vector2(Size.x + offset, Size.y + offset);

            Vector2 minPoint = new Vector2(MinPoint.x - size.x, MinPoint.y - size.y);
            Vector2 maxPoint = new Vector2(MinPoint.x + size.x, MinPoint.y + size.y);

            return point.x >= minPoint.x && point.z >= minPoint.y && point.x <= maxPoint.x && point.z <= maxPoint.y;
        }

        public virtual void OnCreated()
        {
        }

        public virtual void ResetChunk()
        {
        }
    }
}
